GskRenderNode *child;
graphene_matrix_t transform;
+ GskMatrixCategory category;
};
static void
}
}
-#define GSK_TRANSFORM_NODE_VARIANT_TYPE "(dddddddddddddddduv)"
+#define GSK_TRANSFORM_NODE_VARIANT_TYPE "(idddddddddddddddduv)"
static GVariant *
gsk_transform_node_serialize (GskRenderNode *node)
graphene_matrix_to_float (&self->transform, mat);
return g_variant_new (GSK_TRANSFORM_NODE_VARIANT_TYPE,
+ self->category,
(double) mat[0], (double) mat[1], (double) mat[2], (double) mat[3],
(double) mat[4], (double) mat[5], (double) mat[6], (double) mat[7],
(double) mat[8], (double) mat[9], (double) mat[10], (double) mat[11],
graphene_matrix_t transform;
double mat[16];
guint32 child_type;
+ gint32 category;
GVariant *child_variant;
GskRenderNode *result, *child;
return NULL;
g_variant_get (variant, GSK_TRANSFORM_NODE_VARIANT_TYPE,
+ &category,
&mat[0], &mat[1], &mat[2], &mat[3],
&mat[4], &mat[5], &mat[6], &mat[7],
&mat[8], &mat[9], &mat[10], &mat[11],
mat[12], mat[13], mat[14], mat[15]
});
- result = gsk_transform_node_new (child, &transform);
+ result = gsk_transform_node_new_with_category (child, &transform, category);
gsk_render_node_unref (child);
gsk_transform_node_new (GskRenderNode *child,
const graphene_matrix_t *transform)
{
- GskTransformNode *self;
-
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
g_return_val_if_fail (transform != NULL, NULL);
+ return gsk_transform_node_new_with_category (child, transform, GSK_MATRIX_CATEGORY_UNKNOWN);
+}
+
+/*<private>
+ * gsk_transform_node_new_with_category:
+ * @child: The node to transform
+ * @transform: The transform to apply
+ * @category: The category @transform belongs to
+ *
+ * Creates a #GskRenderNode that will transform the given @child
+ * with the given @transform.
+ *
+ * The given @category will be used by renderers for optimizations and must
+ * be correct. If you do not know the category of @transform, use
+ * %GSK_MATRIX_CATEGORY_UNKNOWN.
+ *
+ * Returns: A new #GskRenderNode
+ **/
+GskRenderNode *
+gsk_transform_node_new_with_category (GskRenderNode *child,
+ const graphene_matrix_t *transform,
+ GskMatrixCategory category)
+{
+ GskTransformNode *self;
+
self = (GskTransformNode *) gsk_render_node_new (&GSK_TRANSFORM_NODE_CLASS, 0);
self->child = gsk_render_node_ref (child);
graphene_matrix_init_from_matrix (&self->transform, transform);
+ self->category = category;
graphene_matrix_transform_bounds (&self->transform,
&child->bounds,
return &self->transform;
}
+GskMatrixCategory
+gsk_transform_node_get_category (GskRenderNode *node)
+{
+ GskTransformNode *self = (GskTransformNode *) node;
+
+ g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_TRANSFORM_NODE), GSK_MATRIX_CATEGORY_UNKNOWN);
+
+ return self->category;
+}
+
/*** GSK_OFFSET_NODE ***/
typedef struct _GskOffsetNode GskOffsetNode;
G_BEGIN_DECLS
+/*<private>
+ * GskMatrixCategory:
+ * @GSK_MATRIX_CATEGORY_UNKNOWN: The category of the matrix has not been
+ * determined.
+ * @GSK_MATRIX_CATEGORY_ANY: Analyzing the matrix concluded that it does
+ * not fit in any other category.
+ * @GSK_MATRIX_CATEGORY_INVERTIBLE: The matrix is linear independant and
+ * should therefor be invertible. Note that this is not guaranteed
+ * to actually be true due to rounding errors when inverting.
+ * @GSK_MATRIX_CATEGORY_2D: The matrix is a 2D matrix. This is equivalent
+ * to graphene_matrix_is_2d() returning %TRUE. In particular, this
+ * means that Cairo can deal with the matrix.
+ * @GSK_MATRIX_CATEGORY_2D_AFFINE: The matrix is a combination of 2D scale
+ * and 2D translation operations. In particular, this means that any
+ * rectangle can be transformed exactly using this matrix.
+ * @GSK_MATRIX_CATEGORY_2D_TRANSLATE: The matrix is a 2D translation.
+ * @GSK_MATRIX_CATEGORY_IDENTITY: The matrix is the identity matrix.
+ *
+ * The categories of matrices relevant for GSK and GTK. Note that any
+ * category includes matrices of all later categories. So if you want
+ * to for example check if a matrix is a 2D matrix,
+ * `category >= GSK_MATRIX_CATEGORY_2D` is the way to do this.
+ *
+ * Also keep in mind that rounding errors may cause matrices to not
+ * conform to their categories. Otherwise, matrix operations done via
+ * mutliplication will not worsen categories. So for the matrix
+ * multiplication `C = A * B`, `category(C) = MIN (category(A), category(B))`.
+ */
+typedef enum
+{
+ GSK_MATRIX_CATEGORY_UNKNOWN,
+ GSK_MATRIX_CATEGORY_ANY,
+ GSK_MATRIX_CATEGORY_INVERTIBLE,
+ GSK_MATRIX_CATEGORY_2D_AFFINE,
+ GSK_MATRIX_CATEGORY_2D_TRANSLATE,
+ GSK_MATRIX_CATEGORY_IDENTITY
+} GskMatrixCategory;
+
typedef struct _GskRenderNodeClass GskRenderNodeClass;
#define GSK_IS_RENDER_NODE_TYPE(node,type) (GSK_IS_RENDER_NODE (node) && (node)->node_class->node_type == (type))
GskRenderNode * gsk_cairo_node_new_for_surface (const graphene_rect_t *bounds,
cairo_surface_t *surface);
+GskRenderNode * gsk_transform_node_new_with_category (GskRenderNode *child,
+ const graphene_matrix_t *transform,
+ GskMatrixCategory category);
+GskMatrixCategory gsk_transform_node_get_category (GskRenderNode *node);
+
GskRenderNode * gsk_text_node_new_with_bounds (PangoFont *font,
PangoGlyphString *glyphs,
const GdkRGBA *color,